/*
Xern Entity Relocation Network
Copyright (C) 2011 Ronie Salgado <roniesalg@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include <stdio.h>
#include <string.h>
#include "Xern/FileSystem.hpp"
#include "MapData.hpp"
#include "MapLoader.hpp"
#include "MapProcessor.hpp"
#include "RegionWriter.hpp"

using namespace MapXern;

void PrintVersion()
{
	printf("MapXern version 0.1\n");
}

void PrintHelp()
{
	printf("MapXern [options] <input>\n");
}

static Matrix3 QooleMatrix(
		1.0f, 0.0f, 0.0f,
		0.0f, 0.0f, 1.0f,
		0.0f, -1.0f, 0.0f
);

int main(int argc, const char *argv[])
{
	std::string inputFile;
	std::string outputFile;
	bool useQoole = false;
	float unitScale = 0.025f; // Quake units are inches.

	// Parse the command line.
	for(int i = 1; i < argc; i++)
	{
		if(!strcmp(argv[i], "-help"))
		{
			PrintHelp();
			return 0;
		}
		else if(!strcmp(argv[i], "-version"))
		{
			PrintVersion();
			return 0;
		}
		else if(!strcmp(argv[i], "-qoole"))
		{
			useQoole = true;
			return 0;
		}
		else if(!strcmp(argv[i], "-scale"))
		{
			if(argc == i+1)
			{
				PrintHelp();
				return 1;
			}

			unitScale = atof(argv[++i]);
		}
		else if(!strcmp(argv[i], "-o"))
		{
			if(argc == i+1)
			{
				PrintHelp();
				return 1;
			}

			outputFile = argv[++i];
		}
		else
		{
			inputFile = argv[i];
		}
	}

	// Check the command line.
	if(inputFile.empty())
	{
		PrintHelp();
		return 0;
	}

	if(!PathExists(inputFile))
	{
		inputFile = inputFile + ".xql";
		if(!PathExists(inputFile))
		{
			fprintf(stderr, "Failed to find input file '%s'\n", inputFile.c_str());
			return 1;
		}
	}

	if(outputFile.empty())
		outputFile = FileWithoutExtension(inputFile) + ".xrgn";

	// Create a transformation for loading.
	Transform trans;

	// Use an special transform for qoole maps.
	if(useQoole || FileExtension(inputFile) == ".xql")
	{
		trans.SetMatrix(QooleMatrix);
		unitScale = 0.01f; // wxQoole uses centimeters.
	}

	// Copy the transform.
	Transform tranNotScale = trans;

	// Scale the units.
	Matrix3 scaleMatrix = ScaleMatrix3(unitScale, unitScale, unitScale);
	trans.SetMatrix(trans.GetMatrix() * scaleMatrix);

	// Load the map.
	printf("Loading map '%s'...\n", inputFile.c_str());

	boost::shared_ptr<Object> root = LoadMap(inputFile, trans, tranNotScale, unitScale);
	if(!root)
	{
		printf("FAILED\n");
		return -1;
	}

	printf("DONE\n");

	// Process the map.
	printf("Initial processing\n");

	// Normalize brushes.
	printf("Normalize brushes... ");
	root->Traverse(BrushProcessor(NormalizeBrush));
	printf("Done\n");

	printf("Processing faces...");
	root->Traverse(FaceProcessor(SortFaceVertices));
	root->Traverse(FaceProcessor(GenerateTexCoords));
	root->Traverse(FaceProcessor(TriangulateFace));
	root->Traverse(FaceProcessor(GenerateTBN));
	printf("Done\n");

	// TODO: Produce collision shapes.
	// TODO: Generate hierarchical subdivision.
	// TODO: Static lighting.

	// Write the region.
	printf("Writing region file '%s'...\n", outputFile.c_str());
	if(!WriteRegion(root, outputFile))
	{
		return 1;
	}

	printf("Done\n");

	return 0;
}
